package liziy.spring.core.classreading.type;

import cn.liziy.service.impl.UserServiceImpl;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * 简单注解元素处理类
 * @author Liziy
 * @date 2020/12/17 9:34
 **/
public class SimpleAnnotatedMetadata implements AnnotatedMetadata {

    private Class<?> cls;
    private Set<Class<?>> annotationTypes;
    private static List<Class<?>> defaultAnnotations = new ArrayList<>();
    private Class<? extends Annotation> annotationType;
    private boolean isResolver = false;

    static {
        defaultAnnotations.add(Documented.class);
        defaultAnnotations.add(Target.class);
        defaultAnnotations.add(Retention.class);
    }

    public SimpleAnnotatedMetadata(Class<?> cls) {
        this.cls = cls;
        //根据提供的类对象获取类上面所有的注解并复制属性
        this.annotationTypes = getAllAnnotationTypesByClass(cls);
    }

    private Set<Class<?>> getAllAnnotationTypesByClass(Class<?> cls) {
        Set<Class<?>> annotationTypes = new LinkedHashSet<>();
        //获取当前类上面所有的注解对象
        Annotation[] annotations = cls.getAnnotations();
        for (Annotation annotation : annotations) {
            //获取注解类的类型
            Class<? extends Annotation> annotationType = annotation.annotationType();
            //处理前需要将元注解排除
            if (isJDKDefaultAnnotation(annotationType)) {
                continue;
            }
            if (!isResolver) {
                this.annotationType = annotationType;
                isResolver = true;
            }
            // 添加非元注解到集合中
            annotationTypes.add(annotationType);
            // 递归查找非元注解中所有注解
            annotationTypes.addAll(getAllAnnotationTypesByClass(annotationType));
        }
        return annotationTypes;
    }

    @Override
    public Set<Class<?>> getAnnotationTypes() {
        return annotationTypes;
    }

    @Override
    public Class<? extends Annotation> getAnnotationType() {
        return annotationType;
    }

    /**
     * 判断处理注解类型是否为元注解
     * @param annotationType
     * @return
     */
    private boolean isJDKDefaultAnnotation(Class<?> annotationType) {
        return defaultAnnotations.contains(annotationType);
    }

    public static void main(String[] args) {
        Class<UserServiceImpl> userServiceClass = UserServiceImpl.class;
        SimpleAnnotatedMetadata metadata = new SimpleAnnotatedMetadata(userServiceClass);
        Set<Class<?>> allAnnotationTypesByClass = metadata.getAllAnnotationTypesByClass(userServiceClass);
        for (Class e : allAnnotationTypesByClass) {
            System.out.println(e);
        }
        System.out.println("===========");
        System.out.println(metadata.getAnnotationType());

    }

    @Override
    public boolean isInterface() {
        return this.cls.isInterface();
    }

    @Override
    public boolean isAbstract() {
        return Modifier.isAbstract(this.cls.getModifiers());
    }

    @Override
    public String getBeanName() {
        return this.cls.getName();
    }

    @Override
    public Class<?> getBeanClass() {
        return this.cls;
    }
}
